package com.shiroha.video.service.impl;

import com.shiroha.common.utils.FileUtils;
import com.shiroha.video.jellyfin.client.JellyfinClient;
import com.shiroha.video.jellyfin.client.exception.JellyfinException;
import com.shiroha.video.jellyfin.client.request.ImageQueryParams;
import com.shiroha.video.jellyfin.client.request.ItemMetaData;
import com.shiroha.video.jellyfin.client.request.ItemQueryParams;
import com.shiroha.video.jellyfin.client.response.ImageInfo;
import com.shiroha.video.jellyfin.client.response.Item;
import com.shiroha.video.jellyfin.client.response.MediaResponse;
import com.shiroha.video.pojo.dto.WorkMetaData;
import com.shiroha.video.service.IJellyfinService;
import feign.Response;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.retry.support.RetryTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;
import java.util.UUID;

@Service
@RequiredArgsConstructor
@Slf4j
public class JellyfinServiceImpl implements IJellyfinService {

    @Value("${app.jellyfin.server_url}")
    private String serverUrl;

    @Value("${app.jellyfin.api_key}")
    private String apiKey;

    private final JellyfinClient jellyfinClient;
    private final RetryTemplate retryTemplate;
    private final static String MEDIA_DIR = "deploy/data/jellyfin/media";

    @Override
    public void uploadVideo(WorkMetaData workMetaData, MultipartFile file) throws Exception {
        String extension = FileUtils.getFileExtension(file);
        // 使用作品ID作为文件名
        FileUtils.uploadFile(file, workMetaData.getWorkId() + extension, getUserWorkDirPath(workMetaData.getAuthorId()));
        try(Response response = jellyfinClient.refreshLibrary()){
            if(response.status() != 204) {
                throw new JellyfinException(response.status(), "刷新媒体库失败");
            }
        }
    }

    /**
     * 获取视频的播放 URL 和 封面 URL
     *
     * @param workMetaData 作品元数据
     * @return 包含视频的播放 URL 和封面 URL
     * @throws RuntimeException 当 API 重试次数过多时抛出
     */
    @Override
    public MediaResponse getMediaResponse(WorkMetaData workMetaData) throws RuntimeException {
        // 分别获取播放URL和封面URL
        String itemId = this.getWorkItemId(workMetaData.getAuthorId(), workMetaData.getWorkId());
        String playUrl = this.getVideoPlayUrl(itemId);
        String coverUrl = this.getVideoCoverUrl(itemId);

        return MediaResponse.create()
                .setMessage("视频上传成功")
                .setPlayUrl(playUrl)
                .setCoverUrl(coverUrl);
    }

    /**
     * 更新视频元数据
     *
     * @param itemMetaData 作品元数据
     */
    @Override
    public void updateVideo(ItemMetaData itemMetaData) {

    }

    /**
     * 获取作品预览图
     *
     * @param itemId itemId
     * @param tag    标签
     * @return 图像字节数组
     */
    @Override
    public byte[] getWorkPrimaryImage(String itemId, String tag) {
        ImageQueryParams params = new ImageQueryParams();
        params.setTag(tag);
        return jellyfinClient.getImagePrimaryImage(itemId, params);
    }

    private String getUserWorkDirPath(UUID authorId) {
        return MEDIA_DIR + "/users/" + authorId.toString();
    }

    // 获取视频播放 URL
    private String getVideoPlayUrl(String itemId) {
        return serverUrl + "/Items/" + itemId + "/Download?api_key=" + apiKey;
    }

    // 获取作品对应的 ItemId
    private String getWorkItemId(UUID authorId, Long workId) throws RuntimeException {
        ItemQueryParams params = new ItemQueryParams();
        params.setFilters("IsNotFolder");
        params.setRecursive(true);
        params.setLocationTypes("FileSystem");
        params.setIncludeItemTypes("Movie");
        params.setMediaTypes("Video");
        params.setFields("Path");

        return retryTemplate.execute(context -> {
            // 查询 Item 列表并过滤
            List<Item> items = jellyfinClient.getItem(params).getItems();
            String itemId = items.stream()
                    .filter(item -> this.comparePaths(item.getPath(), authorId, workId))
                    .map(Item::getId)
                    .findFirst()
                    .orElse(null);

            if(itemId == null) {
                log.warn("未找到匹配的 itemId，重试次数: {}", context.getRetryCount());
                throw new RuntimeException("未找到 itemId");
            }

            log.info("成功找到 itemId: {}", itemId);
            return itemId;
        });
    }

    // 根据路径匹配对应的 Item
    private boolean comparePaths(String itemPath, UUID authorId, Long workId) {
        if (itemPath == null || authorId == null || workId == null) {
            return false; // 如果输入参数为 null，直接返回 false
        }

        // 移除文件扩展名
        itemPath = itemPath.replaceAll("\\.[^.]*$", "");

        // 按 "/" 分割路径
        String[] parts = itemPath.split("/");

        // 检查路径是否符合 `/media/{authorId}/{workId}` 的格式
        if (parts.length >= 4 && "media".equals(parts[parts.length - 4]) && "users".equals(parts[parts.length - 3])) {
            String pathAuthorId = parts[parts.length - 2];
            String pathWorkId = parts[parts.length - 1];

            // 比较 authorId 和 workId
            return authorId.toString().equals(pathAuthorId) && workId.toString().equals(pathWorkId);
        }

        return false; // 路径格式不正确
    }

    // 获取视频封面 URL
    private String getVideoCoverUrl(String itemId) throws RuntimeException {
        return retryTemplate.execute(context -> {
            String tag = jellyfinClient.getItemImages(itemId).stream()
                    .filter(imageInfo -> "Primary".equals(imageInfo.getImageType()))
                    .map(ImageInfo::getImageTag)
                    .findFirst()
                    .orElse(null);

            if(tag == null) {
                log.warn("未找到匹配的图像 tag，重试次数: {}", context.getRetryCount());
                throw new RuntimeException("未找到图像 tag");
            }

            log.info("成功找到图像 tag: {}", tag);
            return "/vs/works/" + itemId + "/primary/" + tag;
        });
    }
}
